#include "HandInterface.hpp"
#include <cv.h>

using namespace cv;
using namespace hi;
/*
 *  MLGestureClassifier.cpp
 *  
 *
 *  Created by Rasmus Kyng on 28/01/2011.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */

const Size MLGestureClassifier::perSampleSize(100,100);

MLGestureClassifier::MLGestureClassifier( cv::Ptr< AbstractProbabilityTransformer > probTransPtr ) : probTransPtr(probTransPtr) { } 

MLGestureClassifier::MLGestureClassifier( string pcaName, cv::Ptr< AbstractProbabilityTransformer > probTransPtr ) : probTransPtr(probTransPtr) {
	
	// -- PCA load/prepare -- //
	pca = PCA();
	
	FileStorage fs( pcaName + ".pca.yml" , FileStorage::READ);
	
	if ( !fs.isOpened() ) {
		CV_Error( CV_StsError, "PCA file not found!"); //throws exception!
	}
	
	Mat eigenvectorsForLoading;
	Mat eigenvaluesForLoading;
	Mat meanForLoading;
	
	fs["eigenvectors"] >> eigenvectorsForLoading;
	fs["eigenvalues"] >> eigenvaluesForLoading;
	fs["mean"] >> meanForLoading;

	pca.eigenvectors = eigenvectorsForLoading.clone();
	pca.eigenvalues = eigenvaluesForLoading.clone();
	pca.mean = meanForLoading.clone();

	//TODO CHECK: Is there a way to avoid the xForLoading step with the new file storage system?
}

cv::Mat MLGestureClassifier::getResizedImg( cv::Mat& handImg ) {
	Mat resized;
	resize( handImg, resized, perSampleSize );
	return resized;
}

bool MLGestureClassifier::isHandActive( cv::Mat& handImg ) {
	
	Mat backProj, handHSV;
	//Compute HSV for backprojection
	cvtColor(handImg, handHSV, CV_BGR2HSV);
	//Compute backprojection
	probTransPtr->getBackProjection( handHSV, backProj);

	Mat resized = getResizedImg( backProj );
	Mat dataSampleBeforePCACompression;
	
	double floatImageScale = 1.0/255.0;
	resized.convertTo( dataSampleBeforePCACompression, CV_32FC1, floatImageScale );
	
	CV_Assert( dataSampleBeforePCACompression.isContinuous() );
	dataSampleBeforePCACompression.cols = dataSampleBeforePCACompression.cols*dataSampleBeforePCACompression.rows;
	dataSampleBeforePCACompression.rows = 1;
	
	Mat dataSampleForPrediction;
	
	// compress the vector
	pca.project(dataSampleBeforePCACompression, dataSampleForPrediction);
	
	bool predictedActive = this->predict( dataSampleForPrediction );
	
	return predictedActive;
}